package com.xd.shading.config.sharding;


import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.driver.jdbc.core.datasource.ShardingSphereDataSource;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wangp
 */
@Component
@Slf4j
public class AutoCreateTableHelper implements EnvironmentAware {

    /**
     * 利用Springboot的单例模式，方便使用
     */
    @Getter
    private static AutoCreateTableHelper instance;

    /**
     * 冬天该数据源
     */
    @Resource(name = "shardingDB")
    private  DataSource dataSource;

    /**
     * 数据库的 数据源 : 逻辑表 : 实际表 缓存
     */
    private final Map<String, Map<String, Set<String>>> dsLogicActuallyTableCache = new ConcurrentHashMap<>();


    public Collection<String> autoDetectionSchemeTables(String logicTableName,
                                                        Collection<String> actuallyTableNames, boolean createTable) {
        log.info("创建表的数据源为:{}",dataSource);
        try (Connection connection = dataSource.getConnection()) {
            if (connection == null) {
                log.error("Un found raw jdbc resource to get connection for {}");
                return Collections.emptyList();
            }
            // 获取到缓存的数据源表
            Set<String> cachedTables = getCachedTables(logicTableName);
            // 不存在的表
            List<String> notExistsTables = new ArrayList<>();
            // 已存在的表
            List<String> existsTables = new ArrayList<>();
            actuallyTableNames.forEach(table -> {
                if (cachedTables.contains(table)) {
                    existsTables.add(table);
                } else {
                    notExistsTables.add(table);
                }
            });
            if (notExistsTables.isEmpty()) {
                return existsTables;
            }
            // 如果自动建表，创建那些不存在的表
            if (createTable) {
                String tableLike = cachedTables.stream().findAny().orElse(logicTableName);
                for (String notExistsTable : notExistsTables) {
                    if (DatabaseTableUtil.createTableLike(dataSource, tableLike, notExistsTable)) {
                        cachedTables.add(notExistsTable);
                        existsTables.add(notExistsTable);
                    } else {
                        log.info("Auto create actually table failed");
                    }
                }
            } else {
                // 重新从数据库中刷新数据
                Set<String> databaseTables = DatabaseTableUtil.getActuallyTableName(dataSource, logicTableName);
                if (databaseTables != null) {
                    // 刷新缓存
                    cachedTables.addAll(databaseTables);
                    notExistsTables.removeIf(table -> !databaseTables.contains(table));
                    existsTables.addAll(notExistsTables);
                }
            }
            return existsTables;
        } catch (Exception e) {
            log.error("detection scheme table failed", e);
            return Collections.emptyList();
        }
    }

    private Set<String> getCachedTables(String logicTableName) {
        return DatabaseTableUtil.getActuallyTableName(dataSource, logicTableName);
    }


    @Override
    public void setEnvironment(Environment environment) {
        instance = this;
    }


}

